package com.apes.fn.rpt.profit;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 毛利报表
 */
@Service("grossProfitService")
public class GrossProfitService extends DomainService {

    @Autowired
    private GrossProfitRepository grossProfitRepository;
    @Autowired
    private GrossProfitDao grossProfitDao;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private RptGrossProfitService rptGrossProfitService;


    /***
     * 创建
     */
    public GrossProfit create(SimpleRequest request) {
        GrossProfit grossProfit = request.getO(GrossProfit.class);
        return grossProfitRepository.save(grossProfit);
    }


    /***
     * 批量日结计算毛利报表
     */

    public void batchDayKnot(SimpleRequest request) {
        JSONObject requestJO = request.getJO();
        Date startDate = requestJO.getDate("startDate");
        Date endDate = requestJO.getDate("endDate");


        while (startDate.before(endDate)) {
            //汇总当日毛利报表
            rptGrossProfitService.processByDate(startDate);
//            JSONArray grossProfitItems = grossProfitDao.queryGrossProfit(new JSONObject(MapUtil.mapper(
//                    "P_DATE", startDate
//            )));
//            //写入毛利报表
//            insertGrossProfit(grossProfitItems);
//            //已记账毛利报表刷新
//            grossProfitRefresh(startDate);

            startDate = DateUtil.add(startDate, Calendar.DATE, 1);
        }
    }

    /***
     * 批量日结计算毛利报表(不重汇代记账数据)
     */

    public void batchDayKnotWithoutRefresh(SimpleRequest request) {
        JSONObject requestJO = request.getJO();
        Date startDate = requestJO.getDate("startDate");
        Date endDate = requestJO.getDate("endDate");


        while (startDate.before(endDate)) {
            //汇总当日毛利报表
            rptGrossProfitService.processByDateWithoutRefresh(startDate);

            startDate = DateUtil.add(startDate, Calendar.DATE, 1);
        }
    }

    /***
     * 日结计算毛利报表
     */

    public void rptGrossProfit(SimpleRequest request) {
        Date P_DATE = getTaskDate(request);
        //汇总当日毛利报表
        rptGrossProfitService.processByDate(P_DATE);
        //写入毛利报表
//        insertGrossProfit(grossProfitItems);
        //已记账毛利报表刷新
//        grossProfitRefresh(P_DATE);
    }
    /***
     * 获取统计sql
     * @return
     */

    public Map getTotalSql(SimpleRequest request) {

        Map totalSql = rptGrossProfitService.getTotalSql(new Date());
        return totalSql;
    }

    /**
     * 已记账毛利报表刷新
     *
     * @param P_DATE
     */
//    private void grossProfitRefresh(Date P_DATE) {
//
//        grossProfitDao.queryGrossProfitByRefresh(new JSONObject(MapUtil.mapper(
//                "P_DATE", P_DATE
//        ))).stream().forEach(item -> {
//            JSONObject grossProfitItem = (JSONObject) item;
//            GrossProfit grossProfit = grossProfitRepository.findOne(JpaDsl.toCriteriaByEq("statisticsDate", grossProfitItem.getDate("DOCUMENT_DATE"),
//                    "dept.id", grossProfitItem.getString("DEPT_ID"), "type", grossProfitItem.getString("SERVE_TYPE_NAME"), "incomeCategories",
//                    grossProfitItem.getString("INCOME_CATEGORIES"))).orElse(null);
//                if (Objects.isNull(grossProfit)){
//                    //新增项目
//                    grossProfit = new GrossProfit();
//                    grossProfit.setUnBillAmount(0);
//                    grossProfit.setTimes(grossProfitItem.getDoubleValue("TIMES"));
//                    grossProfit.setAmtCost(grossProfitItem.getDoubleValue("COST"));
//                    grossProfit.setAmtSale(grossProfitItem.getDoubleValue("PRICE_TOTAL"));
//                    grossProfit.setType(grossProfitItem.getString("SERVE_TYPE_NAME"));
//                    grossProfit.setProfitRate(grossProfitItem.getDoubleValue("GROSS_RATE"));
//                    grossProfit.setStatisticsDate(grossProfitItem.getDate("DOCUMENT_DATE"));
//                    grossProfit.setBillAmount(grossProfitItem.getDoubleValue("PRICE_TOTAL"));
//                    grossProfit.setAmtProfit(grossProfitItem.getDoubleValue("GROSS_PROFIT"));
//                    grossProfit.setManHourCost(grossProfitItem.getDoubleValue("MAN_HOUR_COST"));
//                    grossProfit.setAccessoryCost(grossProfitItem.getDoubleValue("ACCESSORY_COST"));
//                    grossProfit.setIncomeCategories(grossProfitItem.getString("INCOME_CATEGORIES"));
//                    grossProfit.setAmtMaterialCost(grossProfitItem.getDoubleValue("CONSUMABLE_USE"));
//                    grossProfit.setDept(deptRepository.findOne(grossProfitItem.getString("DEPT_ID")));
//                    grossProfit.setCompany(partyRoleRepository.findOne(grossProfitItem.getString("COMPANY_ID")));
//                    grossProfit.setPlatformManagementFee(grossProfitItem.getDoubleValue("PLATFORM_MANAGEMENT_FEE"));
//                    grossProfit.setSupplyChainManagementFee(grossProfitItem.getDoubleValue("SUPPLY_CHAIN_MANAGEMENT_FEE"));
//                    grossProfitRepository.saveAndFlush(grossProfit);
//                }else {
//                    //刷新成本和毛利
//                    grossProfit.setUnBillAmount(Arith.sub(grossProfit.getUnBillAmount(), grossProfitItem.getDoubleValue("PRICE_TOTAL")));
//                    grossProfit.setBillAmount(Arith.add(grossProfit.getBillAmount(), grossProfitItem.getDoubleValue("PRICE_TOTAL")));
//                    grossProfit.setAmtCost(Arith.add(grossProfit.getAmtCost(), grossProfitItem.getDoubleValue("COST")));
//                    grossProfit.setAmtMaterialCost(Arith.add(grossProfit.getAmtMaterialCost(), grossProfitItem.getDoubleValue("CONSUMABLE_USE")));
//                    grossProfit.setAccessoryCost(Arith.add(grossProfit.getAccessoryCost(), grossProfitItem.getDoubleValue("ACCESSORY_COST")));
//                    grossProfit.setManHourCost(Arith.add(grossProfit.getManHourCost(), grossProfitItem.getDoubleValue("MAN_HOUR_COST")));
//                    grossProfit.setSupplyChainManagementFee(Arith.add(grossProfit.getSupplyChainManagementFee(), grossProfitItem.getDoubleValue("SUPPLY_CHAIN_MANAGEMENT_FEE")));
//                    grossProfit.setPlatformManagementFee(Arith.add(grossProfit.getPlatformManagementFee(), grossProfitItem.getDoubleValue("PLATFORM_MANAGEMENT_FEE")));
//                    grossProfit.setAmtProfit(grossProfit.getAmtSale() - grossProfit.getAmtCost() - grossProfit.getPlatformManagementFee() - grossProfit.getSupplyChainManagementFee());
//                    grossProfit.setProfitRate(grossProfit.getAmtSale() == 0 ? 0 : grossProfit.getAmtProfit() / grossProfit.getAmtSale());
//                    grossProfitRepository.saveAndFlush(grossProfit);
//                }
//        });
//    }


    /***
     * 获取日结执行日期
     */
    public Date getTaskDate(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        if (tempJson.get("taskDate") == null) throw new RuntimeException("请输入正确的执行时间");
        if (tempJson.get("taskDate") instanceof Date) {
            return tempJson.getDate("taskDate");
        } else {
            try {
                return DateUtil.parse(tempJson.getString("taskDate"));
            } catch (Exception e) {
                throw new RuntimeException("请按照正确的时间格式传入，格式：yyyy-MM-dd");
            }
        }
    }

    /***
     * 插入明细行
     */
    public void insertGrossProfit(JSONArray grossProfitItems) {
        grossProfitItems.forEach(json -> {
            drawGrossProfit((JSONObject) json);
        });

    }

    /**
     * 绘制毛利报表
     *
     * @param grossProfitItem
     */
    public void drawGrossProfit(JSONObject grossProfitItem) {
        GrossProfit grossProfit = grossProfitRepository.findOne(JpaDsl.toCriteriaByEq("statisticsDate", grossProfitItem.getDate("CREATE_DATE"),
                "dept.id", grossProfitItem.getString("DEPT_ID"), "type", grossProfitItem.getString("SERVE_TYPE_NAME"), "incomeCategories",
                grossProfitItem.getString("INCOME_CATEGORIES"))).orElse(new GrossProfit());
//        grossProfit.setId(sequenceService.getId(GrossProfit.CONST_TABLE_NAME));
        grossProfit.setCompany(partyRoleRepository.findOne(grossProfitItem.getString("COMPANY_ID")));
        grossProfit.setDept(deptRepository.findOne(grossProfitItem.getString("DEPT_ID")));
        grossProfit.setType(grossProfitItem.getString("SERVE_TYPE_NAME"));
        grossProfit.setTimes(grossProfitItem.getDoubleValue("TIMES"));
        grossProfit.setIncomeCategories(grossProfitItem.getString("INCOME_CATEGORIES"));
        grossProfit.setAmtSale(grossProfitItem.getDoubleValue("AMOUNT"));
        grossProfit.setUnBillAmount(Arith.sub(grossProfitItem.getDoubleValue("AMOUNT"), grossProfitItem.getDoubleValue("PRICE_TOTAL")));
        grossProfit.setBillAmount(grossProfitItem.getDoubleValue("PRICE_TOTAL"));
        grossProfit.setAmtCost(grossProfitItem.getDoubleValue("COST"));
        grossProfit.setAmtMaterialCost(grossProfitItem.getDoubleValue("CONSUMABLE_USE"));
        grossProfit.setAccessoryCost(grossProfitItem.getDoubleValue("ACCESSORY_COST"));
        grossProfit.setManHourCost(grossProfitItem.getDoubleValue("MAN_HOUR_COST"));
        grossProfit.setSupplyChainManagementFee(grossProfitItem.getDoubleValue("SUPPLY_CHAIN_MANAGEMENT_FEE"));
        grossProfit.setPlatformManagementFee(grossProfitItem.getDoubleValue("PLATFORM_MANAGEMENT_FEE"));
        grossProfit.setAmtProfit(grossProfitItem.getDoubleValue("GROSS_PROFIT"));
        grossProfit.setProfitRate(grossProfitItem.getDoubleValue("GROSS_RATE"));
        grossProfit.setStatisticsDate(grossProfitItem.getDate("CREATE_DATE"));
        grossProfitRepository.saveAndFlush(grossProfit);
    }


    /***
     * 批量更新资金收入单门店
     * 批量更新二手车公司
     */

    /***
     * 凭证
     * 资金收入单
     * 车险佣金
     * 零售明细
     * 付款方式
     * 二手车
     */


    /***
     * 销售
     */
    public Map querySales(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return grossProfitDao.querySales(queryCondition);
    }

    /***
     * 已记账成本
     */
    public Map queryVoucher(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return grossProfitDao.queryVoucher(queryCondition);
    }

    /***
     * 配件成本
     */
    public Map queryVoucher_accessory(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        queryCondition.put("cost_type","accessory");
        return grossProfitDao.queryVoucher(queryCondition);
    }

    /***
     * 配件成本
     */
    public Map queryVoucher_manHour(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        queryCondition.put("cost_type","manHour");
        return grossProfitDao.queryVoucher(queryCondition);
    }

    /***
     * 无成本项
     */
    public void queryError(SimpleRequest request) {
        JSONObject param = request.getJO();
        JSONObject data = param.getJSONObject("data"); // 表单数据
        JSONObject rowData = data.getJSONObject("node"); // 选中行
        rowData.getString("TYPE");
        throw new RuntimeException(rowData.getString("TYPE") + "无成本项！");
    }

    /***
     * 资金收入
     */
    public Map queryMoneyIncome(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryMoneyIncome(queryCondition));
    }

    /***
     * 定损介绍费
     */
    public Map querySettleExpense(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.querySettleExpense(queryCondition));
    }

    /**
     * 车险佣金
     */
    public Map queryPolicyInformation(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryPolicyInformation(queryCondition));
    }

    /***
     * 二手车服务费
     */
    public Map queryUsedCar(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryUsedCar(queryCondition));
    }

    /***
     * 用户储值/定金
     */
    public Map queryRetailOrderAndAdvancePayment(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryRetailOrderAndAdvancePayment(queryCondition));
    }

    /***
     * 年卡
     */
    public Map queryRetailOrder(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryRetailOrder(queryCondition));
    }

    /***
     * 储值/定金消费
     */
    public Map queryRetailOrderCost_recharge(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryRetailOrderCost_recharge(queryCondition));
    }

    /***
     * 年卡消费
     */
    public Map queryRetailOrderCost_yearCard(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryRetailOrderCost_yearCard(queryCondition));
    }

    /***
     * 耗材领用
     */
    public Map queryConsumableUse(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryConsumableUse(queryCondition));
    }
    /***
     * 会员联盟结算
     */
    public Map queryCrossCompany(SimpleRequest request) {
        JSONObject queryCondition = parseQueryCondition(request);
        return packageReturnArray(grossProfitDao.queryCrossCompany(queryCondition));
    }


    /***
     * 解析查询条件
     */
    private JSONObject parseQueryCondition(SimpleRequest request) {
        JSONObject param = request.getJO();
        JSONObject queryCondition = new JSONObject();
        Integer page = param.getInteger("page");
        Integer size = param.getInteger("size");
        queryCondition.put("start", (page - 1) * size);
        queryCondition.put("end", page * size);
        JSONObject data = param.getJSONObject("data"); // 表单数据
        JSONObject rowData = data.getJSONObject("node"); // 选中行
        int showType = data.getIntValue("_showType"); // 显示类型

        String sSQL = "";

        if (data.get("STATISTICS_DATE") != null && data.getJSONArray("STATISTICS_DATE").size() != 0) {
            queryCondition.put("STATISTICS_DATE_MIN",
                    parseDateString(data.getJSONArray("STATISTICS_DATE").getString(0)));
            queryCondition.put("STATISTICS_DATE_MAX",
                    parseDateString(data.getJSONArray("STATISTICS_DATE").getString(1)));

            // 拼接SQL
            if (showType == 0) {
                queryCondition.put("CREATE_DATE", rowData.getDate("STATISTICS_DATE"));
                sSQL += " AND X.CREATE_DATE  < :CREATE_DATE +1 AND X.CREATE_DATE >= :CREATE_DATE";
            } else if (showType == 1) {
                queryCondition.put("CREATE_DATE", rowData.getString("STATISTICS_DATE"));
                sSQL += contactSqlByMonth(queryCondition.getString("CREATE_DATE"),
                        queryCondition.getDate("STATISTICS_DATE_MIN"), queryCondition.getDate("STATISTICS_DATE_MAX"));
            } else {
                sSQL += " AND X.CREATE_DATE >= :STATISTICS_DATE_MIN  AND X.CREATE_DATE < :STATISTICS_DATE_MAX+1";
            }
        } else {
            throw new RuntimeException("查询其他关联数据时统计日期不允许为空");
        }


        sSQL += " AND X.DEPT_ID = :DEPT_ID AND X.TYPE = :TYPE";

        queryCondition.put("SQL", sSQL);
        queryCondition.put("DEPT_ID", rowData.getString("DEPT_ID"));
        queryCondition.put("TYPE", rowData.getString("TYPE"));
        if ("rpt.grossProfit.queryCrossCompanyIncome".equals(param.getString("queryid")))queryCondition.put("TYPE2", "in");
        if ("rpt.grossProfit.queryCrossCompanyPay".equals(param.getString("queryid")))queryCondition.put("TYPE2", "out");
        return queryCondition;
    }

    /***
     * 处理前端时间
     */

    private Date parseDateString(String str) {
        str = str.replace("Z", " UTC");//是空格+UTC
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");//格式化的表达式
        try {
            return format.parse(str);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /***
     * 包装返回数据
     */
    private Map packageReturnArray(JSONArray array) {
        return MapUtil.mapper(
                "content", array,
                "total", array.size(),
                "size", array.size()
        );
    }

    /***
     * 判断是否跨月
     */
    private boolean isCrossMonth(Date STATISTICS_DATE_MIN, Date STATISTICS_DATE_MAX) {
        return !DateUtil.format(STATISTICS_DATE_MIN, "yyyy-MM")
                .equals(DateUtil.format(STATISTICS_DATE_MAX, "yyyy-MM"));
    }

    /***
     * 判断是否头部
     */
    private boolean isQueryMonthHead(String CREATE_DATE, Date STATISTICS_DATE_MIN) {
        return CREATE_DATE.equals(DateUtil.format(STATISTICS_DATE_MIN, "yyyy-MM"));
    }

    /***
     * 判断是否尾部
     */
    private boolean isQueryMonthTail(String CREATE_DATE, Date STATISTICS_DATE_MAX) {
        return CREATE_DATE.equals(DateUtil.format(STATISTICS_DATE_MAX, "yyyy-MM"));
    }

    /***
     * 用于拼接查询月份的SQL
     */
    public String contactSqlByMonth(String CREATE_DATE, Date STATISTICS_DATE_MIN, Date STATISTICS_DATE_MAX) {
        if (isCrossMonth(STATISTICS_DATE_MIN, STATISTICS_DATE_MAX)) {
            if (isQueryMonthHead(CREATE_DATE, STATISTICS_DATE_MIN)) {
                String lastDay = DateUtil.format(DateUtil.getMonthLastDay(STATISTICS_DATE_MIN), DateUtil.SHOW_DATE_FORMAT) + " 23:59:59";
                return " AND X.CREATE_DATE > :STATISTICS_DATE_MIN  AND X.CREATE_DATE <= TO_DATE('" + lastDay + "','yyyy-mm-dd hh24:mi:ss')";
            } else if (isQueryMonthTail(CREATE_DATE, STATISTICS_DATE_MAX)) {
                String firstDay = DateUtil.format(DateUtil.getMonthFirstDay(STATISTICS_DATE_MAX), DateUtil.SHOW_DATE_FORMAT) + " 00:00:00";
                return " AND X.CREATE_DATE >= TO_DATE('" + firstDay + "','yyyy-mm-dd hh24:mi:ss')  AND X.CREATE_DATE < :STATISTICS_DATE_MAX+1";
            } else {
                Date date = DateUtil.parse(CREATE_DATE + "-01");
                String firstDay = DateUtil.format(DateUtil.getMonthFirstDay(date), DateUtil.SHOW_DATE_FORMAT) + " 00:00:00";
                String lastDay = DateUtil.format(DateUtil.getMonthLastDay(date), DateUtil.SHOW_DATE_FORMAT) + " 23:59:59";
                return " AND X.CREATE_DATE >= TO_DATE('" + firstDay + "','yyyy-mm-dd hh24:mi:ss')  AND X.CREATE_DATE <= TO_DATE('" + lastDay + "','yyyy-mm-dd hh24:mi:ss')";
            }
        } else {
            return " AND X.CREATE_DATE >= :STATISTICS_DATE_MIN  AND X.CREATE_DATE <:STATISTICS_DATE_MAX+1";
        }
    }
}
